# Check Syntax 插件

import { SourceCode } from 'rspress/theme';

<SourceCode href="https://github.com/web-infra-dev/rsbuild/tree/main/packages/plugin-check-syntax" />

Check Syntax 插件用于分析构建产物中是否存在当前浏览器范围下不兼容的高级语法。如果存在，会将详细信息打印在终端。

## 快速开始

### 安装插件

你可以通过如下的命令安装插件:

import { PackageManagerTabs } from '@theme';

<PackageManagerTabs command="add @rsbuild/plugin-check-syntax -D" />

### 注册插件

你可以在 `rsbuild.config.ts` 文件中注册插件：

```ts title="rsbuild.config.ts"
import { pluginCheckSyntax } from '@rsbuild/plugin-check-syntax';

export default {
  plugins: [pluginCheckSyntax()],
};
```

## 启用检测

注册 Check Syntax 插件后，Rsbuild 会在生产环境构建后进行语法检测。

当 Rsbuild 在构建产物中检测到不兼容的高级语法后，会将错误日志打印在终端，并退出当前构建流程。

### 错误日志

错误日志的格式如下所示，包含代码来源文件、产物位置、错误原因、源代码等信息：

```bash
error   [Syntax Checker] Find some syntax that does not match "ecmaVersion <= 2015":

  Error 1
  source:  /node_modules/foo/index.js:1:0
  output:  /dist/static/js/main.3f7a4d7e.js:2:39400
  reason:  Unexpected token (1:178)
  code:
     9 |
    10 | var b = 2;
    11 |
  > 12 | console.log(() => {
    13 |   return a + b;
    14 | });
    15 |
```

:::tip
目前语法检测是基于 AST parser 来实现的，每次检测时，只能找出文件中的第一个不兼容语法。如果一个文件中存在多个不兼容语法，你需要修复已发现的语法，并重新执行检测。

如果日志中没有显示对应的源码位置，可以尝试将 [output.minify](/config/output/minify) 设置为 false 后再重新构建。
:::

注意，展示源代码信息依赖 source map 文件，你可以配置 [output.sourceMap](/config/output/source-map) 选项，以在生产环境构建时生成 source map 文件。

```js
export default {
  output: {
    sourceMap: {
      js:
        process.env.NODE_ENV === 'production'
          ? 'source-map'
          : 'cheap-module-source-map',
    },
  },
};
```

### 解决方法

当检测到语法错误后，你可以通过以下方式来处理：

- 如果你希望降级该语法，以保证代码具备良好的兼容性，可以通过 `source.include` 配置来编译相应的模块。
- 如果你不希望降级该语法，可以调整项目的 browserslist 范围，调整至与该语法相匹配的范围。
- 如果你不希望对某些产物进行语法检查，可用 `checkSyntax.exclude` 配置排除要检查的文件。

## 选项

### targets

- **类型：** `string[]`
- **默认值：** `当前项目的 browserslist 配置`

`targets` 表示目标浏览器范围，它的值为标准的 browserslist。Check Syntax 插件默认会读取当前项目的 browserslist 配置，通常你不需要手动配置 `targets` 属性。

Rsbuild 会读取 `targets` 的值，并自动推导出构建产物中可以使用的最低 ECMAScript 语法版本，比如 ES5 或 ES2015。

- **示例：**

比如，项目中需要兼容的浏览器为 Chrome 53 以上版本，可以添加以下设置：

```ts
pluginCheckSyntax({
  targets: ['chrome >= 53'],
});
```

Rsbuild 会推导出 `chrome >= 53` 可以使用的 ECMAScript 语法版本为 ES2015，当构建产物中包含 ES2016 或更高的语法时，就会触发语法错误提示。

:::tip
如果你想了解更多 browserslist 的用法，请参考 [「设置浏览器范围」](/guide/advanced/browser-compatibility)。
:::

### ecmaVersion

- **类型：** `3 | 5 | 6 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 'latest'`
- **默认值：** `基于 targets 自动分析`

`ecmaVersion` 表示构建产物中可以使用的最低 ECMAScript 语法版本。

:::tip
在未设置 `ecmaVersion` 的情况下，Check Syntax 插件会基于 `targets` 来推导出对应的 ECMAScript 版本，目前支持的推导范围为 `es5` ~ `es2018`。
:::

- **示例：**

比如，构建产物中可以使用的最低 ECMAScript 语法版本为 ES2020，可以添加以下设置：

```ts
pluginCheckSyntax({
  ecmaVersion: 2020,
});
```

此时，构建产物中可以包含 ES2020 支持的所有语法，比如 optional chaining。

### exclude

- **类型：** `RegExp | RegExp[]`
- **默认值：** `undefined`

`exclude` 用于在检测时排除一部分文件，你可以传入一个或多个正则表达式来匹配源文件的路径，符合正则的文件将会被忽略，不会触发语法检测。

- **示例：**

比如，忽略 `node_modules/foo` 目录下的文件：

```ts
pluginCheckSyntax({
  exclude: /node_modules\/foo/,
});
```
